package cn.harry.cabinet.server.routes

import cn.harry.cabinet.model.entity.Card
import cn.harry.cabinet.repository.CardRepository
import cn.harry.cabinet.server.dto.card.BatchCardRequest
import cn.harry.cabinet.server.dto.card.CardFormRequest
import cn.harry.cabinet.server.dto.card.CardResponse
import cn.harry.cabinet.server.dto.common.ApiResponse
import cn.harry.cabinet.server.dto.common.PaginationInfo
import cn.harry.cabinet.server.dto.common.PaginationResponse
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.delete
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.put
import io.ktor.server.routing.route
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.InternalSerializationApi

/**
 * 卡片API路由
 * 定义卡片管理的RESTful API接口
 */
@OptIn(InternalSerializationApi::class)
fun Route.cardRoutes(cardRepository: CardRepository) {

    route("/api/cards") {

        // 获取所有卡片
        get {
            try {
                withContext(Dispatchers.IO) {
                    val cards = cardRepository.getAll()
                    val cardResponses = CardResponse.fromCardList(cards)

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(cardResponses, "获取卡片列表成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取卡片列表失败", e)
            }
        }

        // 根据ID获取卡片
        get("/{id}") {
            try {
                val id = call.parameters["id"]?.toLongOrNull()
                if (id == null) {
                    call.respondBadRequest("无效的卡片ID")
                    return@get
                }

                withContext(Dispatchers.IO) {
                    val card = cardRepository.getById(id)
                    if (card == null) {
                        call.respondNotFound("卡片不存在")
                        return@withContext
                    }
                    
                    val cardResponse = CardResponse.fromCard(card)
                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(cardResponse, "获取卡片成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取卡片失败", e)
            }
        }

        // 根据卡号获取卡片
        get("/by-number/{cardNumber}") {
            try {
                val cardNumber = call.parameters["cardNumber"]
                if (cardNumber.isNullOrBlank()) {
                    call.respondBadRequest("卡号不能为空")
                    return@get
                }

                withContext(Dispatchers.IO) {
                    val card = cardRepository.getByCardNumber(cardNumber)
                    if (card == null) {
                        call.respondNotFound("卡片不存在")
                        return@withContext
                    }
                    
                    val cardResponse = CardResponse.fromCard(card)
                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(cardResponse, "获取卡片成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取卡片失败", e)
            }
        }

        // 搜索卡片 - 支持分页查询
        get("/search") {
            try {
                val keyword = call.request.queryParameters["keyword"] ?: ""
                val type = call.request.queryParameters["type"]
                val status = call.request.queryParameters["status"]
                val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 1
                val size = call.request.queryParameters["size"]?.toIntOrNull() ?: 20
                
                // 验证分页参数
                if (page <= 0 || size <= 0 || size > 100) {
                    call.respondBadRequest("分页参数无效：页码必须大于0，每页大小必须在1-100之间")
                    return@get
                }

                withContext(Dispatchers.IO) {
                    // 根据条件获取卡片列表
                    val allCards = when {
                        type != null -> cardRepository.getByType(type)
                        status != null -> cardRepository.getByStatus(status)
                        keyword.isNotBlank() -> cardRepository.search(keyword)
                        else -> cardRepository.getAll()
                    }
                    
                    // 计算分页
                    val totalCount = allCards.size.toLong()
                    val offset = (page - 1) * size
                    val paginatedCards = allCards.drop(offset).take(size)
                    
                    val cardResponses = CardResponse.fromCardList(paginatedCards)
                    
                    // 计算总页数
                    val totalPages = if (totalCount == 0L) 0L else (totalCount + size - 1) / size
                    
                    // 构建分页响应
                    val paginationInfo = PaginationInfo(
                        page = page,
                        size = size,
                        total = totalCount,
                        totalPages = totalPages
                    )
                    
                    val paginationResponse = PaginationResponse(
                        data = cardResponses,
                        pagination = paginationInfo
                    )

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(paginationResponse, "搜索卡片成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("搜索卡片失败", e)
            }
        }

        // 根据状态获取卡片
        get("/by-status/{status}") {
            try {
                val status = call.parameters["status"]
                if (status.isNullOrBlank()) {
                    call.respondBadRequest("状态不能为空")
                    return@get
                }

                withContext(Dispatchers.IO) {
                    val cards = cardRepository.getByStatus(status)
                    val cardResponses = CardResponse.fromCardList(cards)

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(cardResponses, "获取卡片列表成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取卡片列表失败", e)
            }
        }

        // 统计卡片数量
        get("/count") {
            try {
                withContext(Dispatchers.IO) {
                    val totalCount = cardRepository.count()
                    val enabledCount = cardRepository.countByStatus(Card.STATUS_ENABLED)
                    val disabledCount = cardRepository.countByStatus(Card.STATUS_DISABLED)
                    
                    val stats = mapOf(
                        "total" to totalCount,
                        "enabled" to enabledCount,
                        "disabled" to disabledCount
                    )

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(stats, "获取统计信息成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取统计信息失败", e)
            }
        }

        // 创建新卡片
        post {
            try {
                val request = call.receive<CardFormRequest>()

                // 验证请求数据
                if (!request.isValid()) {
                    val errors = request.getValidationErrors()
                    call.respondBadRequest(errors.joinToString(", "))
                    return@post
                }
                
                withContext(Dispatchers.IO) {
                    // 验证卡号唯一性
                    val uniqueError = request.validateUniqueCardNumber(cardRepository)
                    if (uniqueError != null) {
                        call.respondBadRequest(uniqueError)
                        return@withContext
                    }
                    
                    val newCard = request.toCard()
                    val cardId = cardRepository.insert(newCard)
                    val createdCard = cardRepository.getById(cardId)
                    
                    if (createdCard == null) {
                        call.respondError("创建卡片失败", Exception("无法获取创建的卡片"))
                        return@withContext
                    }
                    
                    val cardResponse = CardResponse.fromCard(createdCard)

                    call.respond(
                        HttpStatusCode.Created,
                        ApiResponse.success(cardResponse, "创建卡片成功")
                    )
                }
            } catch (e: IllegalArgumentException) {
                call.respondBadRequest(e.message ?: "创建卡片失败")
            } catch (e: Exception) {
                call.respondError("创建卡片失败", e)
            }
        }

        // 批量创建卡片
        post("/batch") {
            try {
                val request = call.receive<BatchCardRequest>()

                // 验证请求数据
                if (!request.isValid()) {
                    val errors = request.getValidationErrors()
                    call.respondBadRequest(errors.joinToString(", "))
                    return@post
                }
                
                withContext(Dispatchers.IO) {
                    // 验证所有卡号唯一性
                    val uniqueErrors = mutableListOf<String>()
                    request.cards.forEach { cardRequest ->
                        val error = cardRequest.validateUniqueCardNumber(cardRepository)
                        if (error != null) {
                            uniqueErrors.add(error)
                        }
                    }
                    
                    if (uniqueErrors.isNotEmpty()) {
                        call.respondBadRequest(uniqueErrors.joinToString(", "))
                        return@withContext
                    }
                    
                    val cards = request.cards.map { it.toCard() }
                    cardRepository.insertAll(cards)
                    
                    call.respond(
                        HttpStatusCode.Created,
                        ApiResponse.success(message = "批量创建${cards.size}张卡片成功")
                    )
                }
            } catch (e: IllegalArgumentException) {
                call.respondBadRequest(e.message ?: "批量创建卡片失败")
            } catch (e: Exception) {
                call.respondError("批量创建卡片失败", e)
            }
        }

        // 更新卡片
        put("/{id}") {
            try {
                val id = call.parameters["id"]?.toLongOrNull()
                if (id == null) {
                    call.respondBadRequest("无效的卡片ID")
                    return@put
                }

                val request = call.receive<CardFormRequest>()
                
                // 验证请求数据
                if (!request.isValid()) {
                    val errors = request.getValidationErrors()
                    call.respondBadRequest(errors.joinToString(", "))
                    return@put
                }

                withContext(Dispatchers.IO) {
                    val existingCard = cardRepository.getById(id)
                    if (existingCard == null) {
                        call.respondNotFound("卡片不存在")
                        return@withContext
                    }
                    
                    // 验证卡号唯一性（排除当前卡片）
                    val uniqueError = request.validateUniqueCardNumber(cardRepository, id)
                    if (uniqueError != null) {
                        call.respondBadRequest(uniqueError)
                        return@withContext
                    }
                    
                    val updatedCard = existingCard.copy(
                        cardNumber = request.cardNumber,
                        name = request.name,
                        type = request.type,
                        remark = request.remark ?: "",  // null 时使用空字符串
                        status = request.status
                    )
                    
                    cardRepository.update(updatedCard)
                    
                    val cardResponse = CardResponse.fromCard(updatedCard)

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(cardResponse, "更新卡片成功")
                    )
                }
            } catch (e: IllegalArgumentException) {
                call.respondBadRequest(e.message ?: "更新卡片失败")
            } catch (e: Exception) {
                call.respondError("更新卡片失败", e)
            }
        }

        // 更新卡片状态
        put("/{id}/status") {
            try {
                val id = call.parameters["id"]?.toLongOrNull()
                if (id == null) {
                    call.respondBadRequest("无效的卡片ID")
                    return@put
                }

                val status = call.request.queryParameters["status"]
                if (status != Card.STATUS_ENABLED && status != Card.STATUS_DISABLED) {
                    call.respondBadRequest("状态必须是 ENABLED 或 DISABLED")
                    return@put
                }

                withContext(Dispatchers.IO) {
                    val existingCard = cardRepository.getById(id)
                    if (existingCard == null) {
                        call.respondNotFound("卡片不存在")
                        return@withContext
                    }
                    
                    cardRepository.updateStatus(id, status)
                    
                    val updatedCard = cardRepository.getById(id)
                    if (updatedCard == null) {
                        call.respondError("更新状态失败", Exception("无法获取更新后的卡片"))
                        return@withContext
                    }
                    
                    val cardResponse = CardResponse.fromCard(updatedCard)

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(cardResponse, "更新卡片状态成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("更新卡片状态失败", e)
            }
        }

        // 删除卡片
        delete("/{id}") {
            try {
                val id = call.parameters["id"]?.toLongOrNull()
                if (id == null) {
                    call.respondBadRequest("无效的卡片ID")
                    return@delete
                }

                withContext(Dispatchers.IO) {
                    val cardToDelete = cardRepository.getById(id)
                    if (cardToDelete == null) {
                        call.respondNotFound("卡片不存在")
                        return@withContext
                    }
                    
                    cardRepository.delete(cardToDelete)
                    call.respond(HttpStatusCode.OK, ApiResponse.success(message = "删除卡片成功"))
                }
            } catch (e: Exception) {
                call.respondError("删除卡片失败", e)
            }
        }
    }
}


/**
 * 私有扩展函数：响应错误请求
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondBadRequest(message: String) {
    respond(
        HttpStatusCode.BadRequest,
        ApiResponse.errorResponse(400, message)
    )
}

/**
 * 私有扩展函数：响应未找到错误
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondNotFound(message: String) {
    respond(
        HttpStatusCode.NotFound,
        ApiResponse.errorResponse(404, message)
    )
}

/**
 * 私有扩展函数：响应服务器错误
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondError(message: String, exception: Exception) {
    // 添加更详细的错误日志
    println("$message: ${exception.javaClass.simpleName} - ${exception.message}")
    exception.printStackTrace()
    
    respond(
        HttpStatusCode.InternalServerError,
        ApiResponse.errorResponse(500, "$message: ${exception.message}")
    )
}
